# -*- coding:utf-8 -*-

import websocket
import datetime
import hashlib
import base64
import hmac
import json
from urllib.parse import urlencode
import time
import ssl
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime
import _thread as thread
import os
import logging
from django.conf import settings
from django.core.files.base import ContentFile
import uuid

logger = logging.getLogger(__name__)


class Ws_Param(object):
    """讯飞TTS参数配置"""
    
    def __init__(self, APPID, APIKey, APISecret, Text, voice_config=None):
        self.APPID = APPID
        self.APIKey = APIKey
        self.APISecret = APISecret
        self.Text = Text
        
        # 默认语音配置
        default_config = {
            'vcn': 'x4_lingxiaoxuan_oral',  # 发音人
            'volume': 50,    # 音量大小
            'speed': 50,     # 语速
            'pitch': 50,     # 音调
        }
        
        # 合并用户配置
        if voice_config:
            default_config.update(voice_config)

        # 公共参数(common)
        self.CommonArgs = {"app_id": self.APPID, "status": 2}
        
        # 业务参数(business)
        self.BusinessArgs = {
            "tts": {
                "vcn": default_config['vcn'],
                "volume": default_config['volume'],
                "rhy": 0,   # 是否返回拼音标注
                "speed": default_config['speed'],
                "pitch": default_config['pitch'],
                "bgs": 0,   # 背景音
                "reg": 0,   # 英文发音方式
                "rdn": 0,   # 合成音频数字发音方式
                "audio": {
                    "encoding": "lame",  # 合成音频格式为mp3
                    "sample_rate": 24000,  # 合成音频采样率
                    "channels": 1,  # 音频声道数
                    "bit_depth": 16, # 合成音频位深
                    "frame_size": 0
                }
            }
        }
        
        self.Data = {
            "text": {
                "encoding": "utf8",
                "compress": "raw",
                "format": "plain",
                "status": 2,
                "seq": 0,
                "text": str(base64.b64encode(self.Text.encode('utf-8')), "UTF8")
            }
        }


class AssembleHeaderException(Exception):
    def __init__(self, msg):
        self.message = msg


class Url:
    def __init__(this, host, path, schema):
        this.host = host
        this.path = path
        this.schema = schema


def sha256base64(data):
    """计算sha256并编码为base64"""
    sha256 = hashlib.sha256()
    sha256.update(data)
    digest = base64.b64encode(sha256.digest()).decode(encoding='utf-8')
    return digest


def parse_url(requset_url):
    """解析URL"""
    stidx = requset_url.index("://")
    host = requset_url[stidx + 3:]
    schema = requset_url[:stidx + 3]
    edidx = host.index("/")
    if edidx <= 0:
        raise AssembleHeaderException("invalid request url:" + requset_url)
    path = host[edidx:]
    host = host[:edidx]
    u = Url(host, path, schema)
    return u


def assemble_ws_auth_url(requset_url, method="GET", api_key="", api_secret=""):
    """构建websocket认证URL"""
    u = parse_url(requset_url)
    host = u.host
    path = u.path
    now = datetime.now()
    date = format_date_time(mktime(now.timetuple()))
    
    signature_origin = "host: {}\ndate: {}\n{} {} HTTP/1.1".format(host, date, method, path)
    signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
                             digestmod=hashlib.sha256).digest()
    signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
    authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
        api_key, "hmac-sha256", "host date request-line", signature_sha)
    authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
    
    values = {
        "host": host,
        "date": date,
        "authorization": authorization
    }

    return requset_url + "?" + urlencode(values)


class TTSAudioGenerator:
    """TTS音频生成器"""
    
    def __init__(self):
        # 从settings获取讯飞API配置
        self.appid = getattr(settings, 'XUNFEI_APPID', '')
        self.apisecret = getattr(settings, 'XUNFEI_APISECRET', '')
        self.apikey = getattr(settings, 'XUNFEI_APIKEY', '')
        self.requrl = 'wss://cbm01.cn-huabei-1.xf-yun.com/v1/private/mcd9m97e6'
        
        if not all([self.appid, self.apisecret, self.apikey]):
            logger.warning("讯飞TTS API配置不完整，请检查settings配置")
    
    def generate_audio(self, text, voice_config=None, output_filename=None):
        """
        生成音频文件
        
        Args:
            text: 要合成的文本
            voice_config: 语音配置字典
            output_filename: 输出文件名，如果不提供则自动生成
            
        Returns:
            tuple: (音频文件路径, 文件大小, 时长)
        """
        if not all([self.appid, self.apisecret, self.apikey]):
            raise ValueError("讯飞TTS API配置不完整")
        
        if not output_filename:
            # 生成唯一文件名
            output_filename = f"tts_{uuid.uuid4().hex}.mp3"
        
        # 确保输出目录存在
        output_dir = os.path.join(settings.MEDIA_ROOT, 'synthesized_audio')
        os.makedirs(output_dir, exist_ok=True)
        output_path = os.path.join(output_dir, output_filename)
        
        # 如果文件已存在，先删除
        if os.path.exists(output_path):
            os.remove(output_path)
        
        try:
            # 创建TTS参数
            wsParam = Ws_Param(
                APPID=self.appid,
                APISecret=self.apisecret,
                APIKey=self.apikey,
                Text=text,
                voice_config=voice_config
            )
            
            # 构建认证URL
            wsUrl = assemble_ws_auth_url(self.requrl, "GET", self.apikey, self.apisecret)
            
            # 创建WebSocket连接
            websocket.enableTrace(False)
            ws = websocket.WebSocketApp(
                wsUrl,
                on_message=lambda ws, msg: self._on_message(ws, msg, output_path),
                on_error=self._on_error,
                on_close=self._on_close
            )
            ws.on_open = lambda ws: self._on_open(ws, wsParam)
            
            # 运行WebSocket
            ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
            
            # 检查文件是否生成成功
            if os.path.exists(output_path):
                file_size = os.path.getsize(output_path)
                # 简单估算时长（假设1KB约等于1秒）
                duration = max(1, file_size // 1024)
                return output_path, file_size, duration
            else:
                raise Exception("音频文件生成失败")
                
        except Exception as e:
            logger.error(f"TTS音频生成失败: {str(e)}")
            raise
    
    def _on_message(self, ws, message, output_path):
        """处理WebSocket消息"""
        try:
            message = json.loads(message)
            code = message["header"]["code"]
            sid = message["header"]["sid"]
            
            if "payload" in message:
                audio = message["payload"]["audio"]['audio']
                audio = base64.b64decode(audio)
                status = message["payload"]['audio']["status"]
                
                if status == 2:
                    logger.info("TTS音频合成完成")
                    ws.close()
                
                if code != 0:
                    errMsg = message.get("message", "未知错误")
                    logger.error(f"TTS API错误: {errMsg}, code: {code}")
                else:
                    # 写入音频文件
                    with open(output_path, 'ab') as f:
                        f.write(audio)

        except Exception as e:
            logger.error(f"处理TTS消息异常: {str(e)}")
    
    def _on_error(self, ws, error):
        """处理WebSocket错误"""
        logger.error(f"TTS WebSocket错误: {error}")
    
    def _on_close(self, ws, close_status_code, close_msg):
        """处理WebSocket关闭"""
        logger.info("TTS WebSocket连接已关闭")
    
    def _on_open(self, ws, wsParam):
        """处理WebSocket连接建立"""
        def run(*args):
            d = {
                "header": wsParam.CommonArgs,
                "parameter": wsParam.BusinessArgs,
                "payload": wsParam.Data,
            }
            d = json.dumps(d)
            logger.info("开始发送TTS文本数据")
            ws.send(d)
        
        thread.start_new_thread(run, ())


# 全局TTS生成器实例
tts_generator = TTSAudioGenerator()


def synthesize_text_to_audio(text, voice_config=None):
    """
    将文本合成为音频
    
    Args:
        text: 要合成的文本
        voice_config: 语音配置字典，包含speed, pitch, volume等参数
        
    Returns:
        tuple: (相对文件路径, 文件大小, 时长)
    """
    try:
        # 生成音频文件
        output_path, file_size, duration = tts_generator.generate_audio(text, voice_config)
        
        # 转换为相对路径
        relative_path = os.path.relpath(output_path, settings.MEDIA_ROOT)
        
        return relative_path, file_size, duration
        
    except Exception as e:
        logger.error(f"文本转音频失败: {str(e)}")
        raise 